package cc.rengu.igas.bsps.core.realize.impl;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.dao.BspsManagerInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsMchntBindInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsUserRoleInfoMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsManagerInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntBindInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsUserRoleInfoMapperImpl;
import cc.rengu.igas.bsps.common.entity.ManagerInfo;
import cc.rengu.igas.bsps.common.entity.MchntBindInfo;
import cc.rengu.igas.bsps.common.entity.UserRoleInfo;
import cc.rengu.igas.bsps.common.enums.BindStatusEnum;
import cc.rengu.igas.bsps.common.enums.BspsMchntTypeEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.realize.UserPermissionCheckService;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户权限检查.
 */
public class UserPermissionCheckServiceImpl implements UserPermissionCheckService {

    RgLogger rglog = RgLog.getLogger(this.getClass().getName());

    /**
     * 进行用户权限检查
     *
     * @param instId  机构号
     * @param userId  用户信息
     * @param mchntNo 商户号
     * @param txnNum  交易类型
     * @return 结果
     * @throws Exception 异常
     */
    @Override
    public boolean checkNormalUserPermission(String instId, String userId, String mchntNo, String txnNum, String appType) throws Exception {

        if (StringUtil.isEmptyOrNull(userId) || StringUtil.isEmptyOrNull(txnNum)) {
            rglog.error("校验用户权限失败，参数为空，checkNormalUserPermission");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        BspsMchntBindInfoMapper bspsMchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
        BspsUserRoleInfoMapper bspsUserRoleInfoMapper = new BspsUserRoleInfoMapperImpl();
        if (StringUtil.isEmptyOrNull(mchntNo)) {
            rglog.info("商户号为空，查询商户绑定关系表信息");
            boolean checkFlag = false;
            List<MchntBindInfo> mchntBindInfoList = bspsMchntBindInfoMapper.selectBspsMchntBindInfoListByUserId(instId, userId);
            if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
                for (MchntBindInfo mchntBindInfo : mchntBindInfoList) {
                    UserRoleInfo userRoleInfo = bspsUserRoleInfoMapper.selectBspsUserRoleInfoByRoleTypeAndTxnNum(instId, mchntBindInfo.getBindUserRole(), txnNum, appType);
                    if (null != userRoleInfo) {
                        checkFlag = true;
                        break;
                    }
                }
            }
            if (!checkFlag) {
                rglog.info("该用户无该交易权限，userId:<{}>,mchntNo:<{}>,txnNum:<{}>", userId, mchntNo, txnNum);
                throw new BizException(RespCodeEnum.ILLEGAL_OPERATION.getRespCode(), RespCodeEnum.ILLEGAL_OPERATION.getRespDesc());
            }
        } else {
            rglog.info("商户号不为空，商户号：" + mchntNo);
            String key = userId + mchntNo;
            MchntBindInfo mchntBindInfo = JSON.parseObject(RedisUtil.onceGet(key), MchntBindInfo.class);
            if (null == mchntBindInfo) {
                mchntBindInfo = bspsMchntBindInfoMapper.selectBspsMchntBindInfoListByUserIdAndMchntNo(instId, userId, mchntNo);
                if (null == mchntBindInfo) {
                    rglog.info("该用户没有该商户绑定信息，userId:<{}>,mchntNo:<{}>", userId, mchntNo);
                    throw new BizException(RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespDesc());
                }
                RedisUtil.onceSet(key, JSON.toJSONString(mchntBindInfo));
            }

            if (!BindStatusEnum.BIND.getStatus().equals(mchntBindInfo.getBindStatus())) {
                rglog.info("该用户商户绑定信息状态非法，userId:<{}>,mchntNo:<{}>,status:<{}>", userId, mchntNo, mchntBindInfo.getBindStatus());
                throw new BizException(RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespCode(), RespCodeEnum.GET_USER_BIND_INFO_ERROR.getRespDesc());
            }
            String userRoleType = mchntBindInfo.getBindUserRole();
            UserRoleInfo userRoleInfo = bspsUserRoleInfoMapper.selectBspsUserRoleInfoByRoleTypeAndTxnNum(instId, userRoleType, txnNum, appType);
            if (null == userRoleInfo) {
                rglog.info("该用户无该交易权限，userId:<{}>,mchntNo:<{}>,txnNum:<{}>", userId, mchntNo, txnNum);
                throw new BizException(RespCodeEnum.ILLEGAL_OPERATION.getRespCode(), RespCodeEnum.ILLEGAL_OPERATION.getRespDesc());
            }
        }

        return true;
    }

    /**
     * 检查拓展经理权限
     *
     * @param instId 机构号
     * @param userId 用户标识
     * @param txnNum 交易码
     * @return 结果
     * @throws Exception 异常
     */
    @Override
    public boolean checkManagerUserPermission(String instId, String userId, String txnNum, String channelId) throws Exception {
        if (StringUtil.isEmptyOrNull(userId) || StringUtil.isEmptyOrNull(txnNum)) {
            rglog.info("校验用户权限失败，参数为空");
            return false;
        }
        String userRole = null;
        if ("WECHAT".equals(channelId)) {
            rglog.info("微信端拓展经理权限校验");
            //根据用户信息中的openId关联查询拓展经理信息
            if (StringUtil.isEmptyOrNull(userId)) {
                rglog.info("该拓展经理无该交易权限，openId:<{}>,txnNum:<{}>", userId, txnNum);
                return false;
            }
            BspsManagerInfoMapper managerInfoMapper = new BspsManagerInfoMapperImpl();
            ManagerInfo managerInfo = managerInfoMapper.selectBspsManagerInfoByOpenId(instId, userId);
            if (null == managerInfo) {
                rglog.info("拓展经理信息为空，openId:<{}>", userId);
                return false;
            }
            userRole = managerInfo.getRoleType();
        } else if ("PCWEB".equals(channelId)) {
            rglog.info("PC端代理商或平台商户权限校验");
            BspsMchntBindInfoMapper mchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
            List<MchntBindInfo> mchntBindInfoList = mchntBindInfoMapper.selectBspsMchntBindInfoListByUserId(instId, userId);
            if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
                List<MchntBindInfo> mchntBindInfos = mchntBindInfoList.stream().filter(item -> item.getBindMchntType().equals(BspsMchntTypeEnum.AGENT_MCHNT.getMchntType())
                        || item.getBindMchntType().equals(BspsMchntTypeEnum.PLAT_MCHNT.getMchntType())).collect(Collectors.toList());
                if (mchntBindInfos.size() != 1) {
                    rglog.info("代理商用户信息错误，userId:<{}>,txnNum:<{}>", userId, txnNum);
                    return false;
                }
                MchntBindInfo mchntBindInfo = mchntBindInfos.get(0);
                userRole = mchntBindInfo.getBindUserRole();
            } else {
                return false;
            }
        }else if ("APP".equals(channelId)) {
            rglog.info("APP端拓展经理权限校验");
            //根据用拓展经理工号关联查询拓展经理信息
            if (StringUtil.isEmptyOrNull(userId)) {
                rglog.info("该拓展经理无该交易权限，userId:<{}>,txnNum:<{}>", userId, txnNum);
                return false;
            }
            BspsManagerInfoMapper managerInfoMapper = new BspsManagerInfoMapperImpl();
            ManagerInfo managerInfo = managerInfoMapper.selectBspsManagerInfoById(instId, userId);
            if (null == managerInfo) {
                rglog.info("拓展经理信息为空，openId:<{}>", userId);
                return false;
            }
            userRole = managerInfo.getRoleType();
        }
        BspsUserRoleInfoMapper bspsUserRoleInfoMapper = new BspsUserRoleInfoMapperImpl();
        UserRoleInfo userRoleInfo = bspsUserRoleInfoMapper.selectBspsUserRoleInfoByRoleTypeAndTxnNum(instId, userRole, txnNum, channelId);
        if (null == userRoleInfo) {
            rglog.info("该角色无该交易权限，userId:<{}>,txnNum:<{}>,角色:<{}>", userId, txnNum, userRole);
            return false;
        }
        return true;
    }


    @Override
    public UserSessionInfo checkSessionStatus(String instId, String sessionId) throws Exception {
        String userSessionInfo = RedisUtil.onceGet(sessionId);
        if (StringUtil.isEmptyOrNull(userSessionInfo)) {
            rglog.error("会话超时，sessionId:<{}>", sessionId);
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        } else {
            RedisUtil.onceExpire(sessionId, BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
            rglog.info("当前会话有效，重置会话有效时长。sessionId:<{}>,sessionExpiryTime:<{}>", sessionId, BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
            return JSON.parseObject(userSessionInfo, UserSessionInfo.class);
        }
    }

    @Override
    public UserSessionInfo checkUserLoginSessionStatus(String instId, String sessionId, String userId) throws Exception {
        String sessionInfo = RedisUtil.onceGet(sessionId);
        if (StringUtil.isEmptyOrNull(sessionInfo)) {
            rglog.info("会话超时，sessionId:<{}>", sessionId);
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        } else {
            UserSessionInfo userSessionInfo = JSON.parseObject(sessionInfo, UserSessionInfo.class);
            if (StringUtil.isEmptyOrNull(userId) || !userId.equals(userSessionInfo.getUserId())) {
                rglog.error("用户未登录");
                throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
            }
            RedisUtil.onceExpire(sessionId, BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
            rglog.info("当前会话有效，重置会话有效时长。sessionId:<{}>,sessionExpiryTime:<{}>", sessionId, BspsAppParamConstant.SESSION_EFFECTIVE_TIME);
            return userSessionInfo;
        }
    }

    @Override
    public boolean checkUserPermission(String instId, String userId, String txnNum, String channelId) throws Exception {
        if (StringUtil.isEmptyOrNull(instId) || StringUtil.isEmptyOrNull(userId) || StringUtil.isEmptyOrNull(txnNum) || StringUtil.isEmptyOrNull(channelId)) {
            rglog.error("校验字段信息为空，instId:<{}>,userId:<{}>,txnNum:<{}>,channelId:<{}>", instId, userId, txnNum, channelId);
            return false;
        }
        rglog.info("商户维度查询");
        BspsMchntBindInfoMapper mchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
        BspsUserRoleInfoMapper userRoleInfoMapper = new BspsUserRoleInfoMapperImpl();
        UserRoleInfo userRoleInfo;
        List<MchntBindInfo> mchntBindInfoList = mchntBindInfoMapper.selectBspsMchntBindInfoListByUserId(instId, userId);
        if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
            rglog.info("商户信息，userId:" + userId);
            for (MchntBindInfo mchntBindInfo : mchntBindInfoList) {
                userRoleInfo = userRoleInfoMapper.selectBspsUserRoleInfoByRoleTypeAndTxnNum(instId, mchntBindInfo.getBindUserRole(), txnNum, channelId);
                if (null != userRoleInfo) {
                    rglog.info("商户拥有交易权限");
                    return true;
                }
            }
        }
        rglog.info("查询拓展经理维度");
        if (!StringUtil.isEmptyOrNull(userId) && !"OPENID".equals(userId) && ("WECHAT".equals(channelId) || "APP".equals(channelId))) {
            BspsManagerInfoMapper bspsManagerInfoMapper = new BspsManagerInfoMapperImpl();
            ManagerInfo managerInfo = null;
            if ("WECHAT".equals(channelId)) {
                managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoByOpenId(instId, userId);
            }else {
                managerInfo = bspsManagerInfoMapper.selectBspsManagerInfoById(instId, userId);
            }
            userRoleInfo = userRoleInfoMapper.selectBspsUserRoleInfoByRoleTypeAndTxnNum(instId, managerInfo.getRoleType(), txnNum, channelId);
            if (null != userRoleInfo) {
                rglog.info("拓展经理拥有交易权限");
                return true;
            }
        }
        return false;
    }
}
